#ifndef position_h
#define position_h

#if HAVE_CONFIG_H
# include <config.h>
#endif

#include <chess.h>
#include <bitboard.h>
#include <move.h>
#include <ttable.h>

#include <assert.h>


#define BB_POS_PIECES(pos, color, type) \
  ((pos)->bb_pieces[(type)] & (pos)->bb_colors[(color)])
#define BB_POS_COLOR(pos, color) \
  (((const position_t*)(pos))->bb_colors[color])
#define BB_POS_ALL(pos) \
  (BB_POS_COLOR((pos), WHITE) | BB_POS_COLOR((pos), BLACK))


typedef struct position_t
{
  bitboard_t bb_colors[2];  // by color
  bitboard_t bb_pieces[6];  // by type
  int squares[64];
  int stm;  // side to move
  unsigned int castling_caps;
  int enpassant;
  int halfmoves;
  int fullmoves;
  hash_key_t key;
  hash_key_t tag;
  hash_key_t pawn_key;
  hash_key_t material_key;
  hash_key_t material_signature;
} position_t;


void position_clear(position_t* pos);
void position_drop_piece(position_t* pos, int square, int side, int piece);
void position_remove_piece(position_t* pos, int square);
void position_move_piece(position_t* pos, int from, int to);
int position_get_square(const position_t* pos, int square);
int position_get_square_side(const position_t* pos, int square);
int position_piece_count(const position_t* pos, int side, int piece);

int position_get_stm(const position_t* pos);
void position_change_stm(position_t* pos);

unsigned int position_get_castling_caps(const position_t* pos);
void position_set_castling_caps(position_t* pos, unsigned int caps);

int position_get_ep_square(const position_t* pos);
void position_set_ep_square(position_t* pos, int ep);

int position_get_half_moves(const position_t* pos);
void position_set_half_moves(position_t* pos, int n);

int position_get_full_moves(const position_t* pos);
void position_set_full_moves(position_t* pos, int n);

hash_key_t position_get_hash_key(const position_t* pos);
hash_key_t position_get_hash_tag(const position_t* pos);
hash_key_t position_get_pawn_hash_key(const position_t* pos);
hash_key_t position_get_material_hash_key(const position_t* pos);
hash_key_t position_get_material_signature(const position_t* pos);

int position_verify_legal(const position_t* pos);

void position_reverse(const position_t* src, position_t* dst);
int position_check_hash(const position_t* pos);

#endif  // position_h
